package org.shangrila.bme.mb;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
import javax.inject.Inject;
import javax.inject.Named;

import org.primefaces.event.RowEditEvent;
import org.primefaces.event.SelectEvent;
import org.shangrila.app.sys.cfg.AppInitInfo;
import org.shangrila.app.sys.shiro.SecUtil;
import org.shangrila.app.wechat.bean.WechatMessageUtils;
import org.shangrila.app.wechat.utils.WeChatUtil;
import org.shangrila.app.wfm.mb.WfmTaskMgrMB;
import org.shangrila.bme.eo.AppFileInfo;
import org.shangrila.bme.eo.BmeContProd;
import org.shangrila.bme.eo.BmeContPurch;
import org.shangrila.bme.eo.BmeContract;
import org.shangrila.bme.eo.BmeCustomer;
import org.shangrila.bme.eo.BmeMaterial;
import org.shangrila.bme.eo.BmeProdBom;
import org.shangrila.bme.eo.BmeWfmService;
import org.shangrila.comm.dao.DbAccess;
import org.shangrila.comm.helper.IDHelper;
import org.shangrila.wfm.core.WfmEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Named
@SessionScoped
public class ContractMB implements Serializable {
	private static final long serialVersionUID = -5951492023664217112L;
	private final Logger log = LoggerFactory.getLogger(this.getClass());

	private String initname="1";
    private BmeContract io = new BmeContract();//录入合同信息
	private List<BmeContProd> vop = new ArrayList<BmeContProd>(); //合同产品
	private List<BmeContPurch> voppm = new ArrayList<BmeContPurch>(); //采购清单
	private BmeContProd selectedp = new BmeContProd();

	private BmeContPurch selectedpm = new BmeContPurch();
	
	private List<BmeCustomer> bmeCustomers; 	
	private BmeCustomer selectedCustomer = new BmeCustomer(); 
	private List<BmeMaterial> bmeMaterials; 	
	private List<BmeMaterial> selectedMaterials = new ArrayList<BmeMaterial>();

	

	//获取相关数据字典
	private List<SelectItem> itemsContractStatus = AppInitInfo.getDropdownList("ContractStatus"); 
	//map keys are by default been used as item labels and that map values are by default been used as item values.
	private LinkedHashMap<String,String> itemsSuppliers = AppInitInfo.getDropdownMap("BmeSupplier","id","name"); 
	private LinkedHashMap<String,String> itemsSysUsers = AppInitInfo.getDropdownMap("SysUser","username","userno");

	private String operator;
	private String contractId="";
	private String contractName="";


	private String uploadedFile="";
	private String uploadedFileImage="";
	
	//附件上传页面参数传递
	private String uploadForType="1";
	private String uploadForId="0";
	private String uploadForName="0";
	
	private String processCheck="wf_htsh";
	private String processUpdate="wf_htbgsq";

	//private DbAccess db = new DbAccess();
	@Inject
	private DbAccess db;
	@Inject
	private BmeCommEntityService bmeCommEntityService;  
	@Inject
	private AttachUploadMB attachUploadMB;
	
	@PostConstruct
    public void init() {
		try{
			newIo();
			operator = SecUtil.getCachedShiroUser().getUserno();
		}
		catch(Exception ex){
			operator="bme";
		}
    }
	//初始化数据
    public void initdata() {
    	log.error("initdata..."+initname);
    	if("0".equals(initname)) {    		
	    	bmeCustomers = bmeCommEntityService.getBmeCustomers();
	    	bmeMaterials = bmeCommEntityService.getBmeMaterials();
	    	attachUploadMB.setVoList(new ArrayList<AppFileInfo>());
	    	newIo();
    	}   
    	initname="1";  //first 0;then 1,not do sth
    }
    
    //接收WFM参数
  	public void initwfm() {
  		WfmTaskMgrMB wfmTaskMgrMB = (WfmTaskMgrMB)AppInitInfo.findSessionBeanByName("wfmTaskMgrMB");
  		if(null != wfmTaskMgrMB) {
  			contractId = wfmTaskMgrMB.getSelectedTask().getServiceNo();
  			/*log.info("initwfm="+contractId);*/
  			queryAction();
  			}			
  	}
  	
    public void newIo() {
    	io = new BmeContract();
    	io.setId(IDHelper.genStrID(20)); 
    	io.setStatus("1");
    	vop = new ArrayList<BmeContProd>();
    	voppm = new ArrayList<BmeContPurch>();
    	selectedp = new BmeContProd();
    	selectedCustomer = new BmeCustomer();     	
    	contractId="";
    	contractName="";
    	attachUploadMB.setVoList(new ArrayList<AppFileInfo>());
    	attachUploadMB.setUploadedFileImage("");
    }    

	//null
	public String nullAction() {
		return null;
	}
	
    //查询信息
	public String queryAction() {		
		//System.out.println("queryAction--");
		String sql = "SELECT m FROM BmeContract m WHERE m.id=?1 OR m.name=?2";
		List<BmeContract> lbc = db.findBySql(sql, new Object[]{contractId,contractName });
		if(lbc.size()>0) {
			io = lbc.get(0);
			selectedCustomer = io.getBmeCustomer();
			vop = io.getBmeContProds();
			voppm = io.getBmeContPurches();

			//附件
			uploadForId=io.getId();
			uploadForName=io.getName();
			sql="SELECT m FROM AppFileInfo m WHERE m.forId=?1 and m.forType=?2";
			attachUploadMB.setVoList(db.findBySql(sql, new Object[]{io.getId(),uploadForType}));
		}
		else {
			io = new BmeContract();
			vop = new ArrayList<BmeContProd>();
			voppm = new ArrayList<BmeContPurch>();
	    	attachUploadMB.setVoList(new ArrayList<AppFileInfo>());
	    	attachUploadMB.setUploadedFileImage("");
		}
				
		return null;
	}
	
	//新增合同
    public void onAddContract() {   
    	newIo();
        AppInitInfo.showMessage("新增合同", "处理成功");
    }

    //提交合同审核流程
    public String checkWfmAction() {
    	if(!validDetailAction()) {
    		return null;
    	}
    	
    	Map<String, Object> args=new HashMap<>();
    	args.put(AppInitInfo.APP_BUSINESS_NO, io.getId());  	
		args.put(AppInitInfo.APP_OPERATOR,"all");			
		args.put(AppInitInfo.APP_BUSINESS_TYPE, uploadForType);
		WfmEngine engine = new WfmEngine();
		engine.startService(engine.getWfmdao().findProcessByName(processCheck).get(0), operator, args);
		
		/*填写业务流程日志*/
		BmeWfmService service = new BmeWfmService();
		service.setId(IDHelper.genStrID(24));
		service.setBusinessId(io.getId());
		service.setBusinessType(uploadForType);
		service.setCreateTime(new Date());
		service.setOperator(operator);
		service.setProcessName(processCheck);
		service.setServiceNo(io.getId());
		io.setStatus("2");
		db.begin();
		db.insert(service);
		db.update(io);
		db.commit();
		AppInitInfo.showMessage("提交合同审核流程", "处理成功");
		
		/*通知合同审单人*/
		String wxno = WechatMessageUtils.getWxnosByRolename("bills_specialist");
		WeChatUtil.sendTextMessage(wxno, "你有一份"+"合同编号："+io.getId()+"合同名称："+io.getName()+"待审！");
    	return null;
    }
    
    //提交合同变更流程
    public String updateWfmAction() {
    	
    	if(!validDetailAction()) {
    		return null;
    	}
    	
    	Map<String, Object> args=new HashMap<>();
    	args.put(AppInitInfo.APP_BUSINESS_NO, io.getId());  	
		args.put(AppInitInfo.APP_OPERATOR,"all");			
		args.put(AppInitInfo.APP_BUSINESS_TYPE, uploadForType);
		WfmEngine engine = new WfmEngine();
		engine.startService(engine.getWfmdao().findProcessByName(processUpdate).get(0), operator, args);
		
		/*填写业务流程日志*/
		BmeWfmService service = new BmeWfmService();
		service.setId(IDHelper.genStrID(24));
		service.setBusinessId(io.getId());
		service.setBusinessType(uploadForType);
		service.setCreateTime(new Date());
		service.setOperator(operator);
		service.setProcessName(processUpdate);
		service.setServiceNo(io.getId());
		io.setStatus("5");
		db.begin();
		db.insert(service);
		db.update(io);
		db.commit();
		AppInitInfo.showMessage("合同变更申请流程", "处理成功");
    	return null;
    }
    
    //保存合同信息
	public String saveAction() {		
		try {
			io.setBmeCustomer(selectedCustomer);
			io.setCreateTime(new Date());
			io.setOperator(operator);
			
			db.beginTransaction();
			db.insert(io);
			db.commitTransaction();
			
			AppInitInfo.showMessage("合同录入", "处理成功");
			uploadForId=io.getId();
			uploadForName=io.getName();

		}catch(Exception e) {			
			AppInitInfo.showMessage("合同录入", "处理失败");
			log.error(e.getLocalizedMessage());
			try {
				db.rollbackTransaction();
			}catch(Exception ex) {	}
		}
		return null;
	}
	
   //合同审核流程：审核操作
	public String checkAction() {		
		try {
			//合同审核状态通过
			io.setStatus("3");
			db.beginTransaction();
			db.update(io);
			db.insert(AppInitInfo.logAppLogInfo(operator, "合同审核流程审核操作", 
					"合同审核流程审核", "1", io.getId(), 
					"审核通过", "合同审核流程之审核", "我的工作", "合同审核页面", 
					"STATUS=3", "STATUS=2", "合同审核通过"));
			db.commitTransaction();
			
			AppInitInfo.showMessage("合同审核", "处理成功");
		}catch(Exception e) {			
			AppInitInfo.showMessage("合同审核", "处理失败");
			log.error(e.getLocalizedMessage());
			try {
				db.rollbackTransaction();
			}catch(Exception ex) {	}
		}
		return null;
	}
    
	//删除产品
    public String delProduct() {
        vop.remove(selectedp);
		db.beginTransaction();
		db.delete(selectedp);
		db.commitTransaction();
		io.setBmeContProds(vop);//needded
        AppInitInfo.showMessage("删除产品", "处理成功");
        return null;
    }
	
	//验证详单操作的有效性
	public boolean validDetailAction(){
		if(null==io.getCreateTime()) {
			AppInitInfo.showMessage("warn","操作无效", "请确保单据主体信息已经保存");
			return false;
		}
		else
			return true;
	}	
	
    //保存产品
	public String saveProduct() {
		if(!validDetailAction()) {
			return null;
		}
			
		List<BmeContProd> bcpList = new ArrayList<BmeContProd>();
		for(BmeMaterial bm : selectedMaterials) {
			selectedp = new BmeContProd();
			selectedp.setId(IDHelper.genStrID(20));
			selectedp.setBmeContract(io);
			selectedp.setContName(io.getName());
			selectedp.setBmeMaterial(bm);
			selectedp.setSupplierId(io.getSupplierId());
			selectedp.setCreateTime(new Date());
			selectedp.setOperator(operator);
			selectedp.setPrice(bm.getSalePrice());
			bcpList.add(selectedp);			
		}
		try {
			db.beginTransaction();
			for(BmeContProd bcp:bcpList) {
				db.insert(bcp);
			}
			db.commitTransaction();
			vop.addAll(bcpList);
			io.setBmeContProds(vop);  //必须设置：不然查询时当前记录不会显示出来
			AppInitInfo.showMessage("产品录入", "处理成功");
			selectedMaterials=null;
	
		}catch(Exception e) {			
			AppInitInfo.showMessage("error","产品录入", "处理失败");
			log.error(e.getLocalizedMessage());
			try {
				db.rollbackTransaction();
			}catch(Exception ex) {	}
		} 	
		return null;
	}
	
	//产品编辑
    public void onRowEdit(RowEditEvent event) {
    	selectedp = vop.get(vop.indexOf((BmeContProd) event.getObject()));
    	//自动计算金额
    	selectedp.setAmount((null==selectedp.getPrice() ? new BigDecimal(0) : selectedp.getPrice()).multiply((null==selectedp.getQuantity() ? new BigDecimal(0) : selectedp.getQuantity())));
    	db.beginTransaction();
    	db.update(selectedp);
    	db.commitTransaction();
    	AppInitInfo.showMessage("产品修改", "处理成功");
    }
	//采购编辑
    public void onPurchRowEdit(RowEditEvent event) {
    	selectedpm = voppm.get(voppm.indexOf((BmeContPurch) event.getObject()));
    	//自动计算金额
    	selectedpm.setAmount((null==selectedpm.getPrice() ? new BigDecimal(0) : selectedpm.getPrice()).multiply((null==selectedpm.getQuantity() ? new BigDecimal(0) : selectedpm.getQuantity())));
    	db.beginTransaction();
    	db.update(selectedpm);
    	db.commitTransaction();
    	AppInitInfo.showMessage("采购修改", "处理成功");
    }   
    
    public void onRowCancel(RowEditEvent event) {
    	AppInitInfo.showMessage("取消修改", "处理成功");
    }

	//生成合同金额
	public void genContractPrice() {
		if(!validDetailAction()) {
			return ;
		}
		//从BmeContProd表生成BmeContract的price数据
		BigDecimal tmp = new BigDecimal(0);
		for(BmeContProd bcp:vop) {
			tmp = tmp.add(null==bcp.getAmount() ? new BigDecimal(0) : bcp.getAmount());
		}
		io.setPrice(tmp);
		db.beginTransaction();
		db.update(io);
		db.commitTransaction();
		AppInitInfo.showMessage("生成合同金额", "处理成功");		
	}
	
	//生成采购清单
	public void onGenPurch() {
		if(!validDetailAction()) {
			return ;
		}
		//从BmeContProd表生成BmeContPurch数据：
		//如果不是BOM产品，则直接复制
		//如果是BOM产品，则需要分解BOM的物料清单进行复制，物料ID相同的则合并计算数量
		voppm = new ArrayList<BmeContPurch>();
		String sql = "delete from BmeContPurch o where o.bmeContract.id=?1";
		try {
			voppm = new ArrayList<BmeContPurch>(); //采购清单
			List<BmeContProd> bom = new ArrayList<BmeContProd>(); 
			//把BOM自制类别的产品暂存起来，其他的直接插入采购清单
			for(BmeContProd bcp:vop) {
				if("2".equals(bcp.getBmeMaterial().getMsort())) {
					bom.add(bcp); 
				}
				else {
					BmeContPurch bcpurch  = new BmeContPurch();
					bcpurch.setId(IDHelper.genStrID(20));
					bcpurch.setBmeContract(bcp.getBmeContract());
					bcpurch.setContName(bcp.getBmeContract().getName());
					bcpurch.setBmeMaterial(bcp.getBmeMaterial());
					bcpurch.setContName(bcp.getContName());
					bcpurch.setSupplierId(bcp.getSupplierId());
					bcpurch.setArea(bcp.getArea());
					
					bcpurch.setPrice(bcp.getPrice());
					bcpurch.setQuantity(bcp.getQuantity());
					bcpurch.setAmount(bcp.getAmount());
					
					bcpurch.setRemarks(bcp.getRemarks());				
					bcpurch.setCreateTime(new Date());
					bcpurch.setOperator(operator);
					voppm.add(bcpurch);
				}
			}
			
			//找出BOM类别的物料清单，每个MID都进行数量和金额计算，生成一个BmeContPurch列表（BOM物料相关）
			sql = "select o from BmeProdBom o where o.pid=?1";
			List<BmeContPurch> bcplist = new ArrayList<BmeContPurch>(); 
			for(BmeContProd bcp:bom) {
				List<BmeProdBom> tmplist = db.findBySql(sql,new Object[] {bcp.getBmeMaterial().getId()});
				if(tmplist.size()>0) {
					for(BmeProdBom bo:tmplist) {  //处理数量:这个地方有坑，不能直接修改和使用bo，否则会把bo提交保存
						BmeContPurch bcpurch  = new BmeContPurch();
						bcpurch.setId(IDHelper.genStrID(20));
						bcpurch.setBmeContract(bcp.getBmeContract());
						bcpurch.setBmeMaterial(getMateriaFromId(bo.getMid()));
						bcpurch.setContName(bcp.getContName());
						bcpurch.setSupplierId(bcp.getSupplierId());
						bcpurch.setPrice(bo.getSalePrice());
						bcpurch.setQuantity(bcp.getQuantity().multiply(bo.getQuantity())); //产品数量乘BOM标准物料的数量
						bcpurch.setAmount(bcpurch.getPrice().multiply(bcpurch.getQuantity()));
						bcpurch.setRemarks(bcp.getRemarks());	
						bcpurch.setArea(bcp.getArea());
						bcpurch.setCreateTime(new Date());
						bcpurch.setOperator(operator);
						bcplist.add(bcpurch);
					}
				}
				else {
					BmeContPurch bcpurch  = new BmeContPurch();
					bcpurch.setId(IDHelper.genStrID(20));
					bcpurch.setBmeContract(bcp.getBmeContract());
					bcpurch.setContName(bcp.getBmeContract().getName());
					bcpurch.setBmeMaterial(bcp.getBmeMaterial());
					bcpurch.setContName(bcp.getContName());
					bcpurch.setSupplierId(bcp.getSupplierId());
					bcpurch.setArea(bcp.getArea());
					bcpurch.setPrice(bcp.getPrice());
					bcpurch.setQuantity(bcp.getQuantity());
					bcpurch.setAmount(bcp.getAmount());
					
					bcpurch.setRemarks(bcp.getRemarks());				
					bcpurch.setCreateTime(new Date());
					bcpurch.setOperator(operator);
					voppm.add(bcpurch);
				}
			}
			
			//以上一步生成的BOM物料相关的BmeContPurch列表为基础，进行合并或者插入操作
			//BOM的合并或插入：MID相同的合并，没有MID则插入
			boolean find=false;
			for(BmeContPurch bpurch:bcplist) { 
				find=false;
				for(BmeContPurch bcp:voppm) { //已有的BmeContPurch
					if(bpurch.getBmeMaterial().getId().equals(bcp.getBmeMaterial().getId()) ) { //合并
						bcp.setQuantity(bpurch.getQuantity().add(bcp.getQuantity()));	//数量相加
						bcp.setAmount(bcp.getPrice().multiply(bcp.getQuantity()));		//金额计算
						find=true;
					}
				}
				if(!find){ //插入
					voppm.add(bpurch);
				}
			}
			
			//db.getEm().flush();
			db.getEm().clear();
			//清除合同下已有清单数据
			sql = "delete from BmeContPurch o where o.bmeContract.id=?1";
			db.beginTransaction();
			db.createQuery(sql).setParameter(1, io.getId()).executeUpdate();//delete 的记录数
			for(BmeContPurch bcp:voppm) {
				db.insert(bcp);
			}
			db.commitTransaction();
			AppInitInfo.showMessage("生成采购清单", "处理成功");
			io.setBmeContPurches(voppm);  //必须设置：不然查询时当前记录不会显示出来
			
		}catch(Exception ex) {
			AppInitInfo.showMessage("生成采购清单", "处理失败");
			log.error(ex.getLocalizedMessage());
			voppm = new ArrayList<BmeContPurch>();
			try{
				db.rollbackTransaction();
				}catch(Exception e) {};		
		}
		
	}
	
    //输入自动完成示例 
    public List<BmeCustomer> completeCustomers(String query) {
        List<BmeCustomer> filteredCusts = new ArrayList<BmeCustomer>(); 
        //filteredCusts.add(new BmeCustomer());
        for (BmeCustomer bc : bmeCommEntityService.getBmeCustomers()) {
            if(bc.getName().toLowerCase().startsWith(query)) {
            	filteredCusts.add(bc);
            }
        }         
        return filteredCusts;
    }    
    
    //输入自动完成示例
    public void onAutoValueChanged(ValueChangeEvent event) {
    	//AppInitInfo.showMessage("onAutoValueChanged", "onAutoValueChanged");
    	selectedCustomer =  (BmeCustomer)event.getNewValue();
    	io.setBmeCustomer(selectedCustomer);
    	io.setCustName(selectedCustomer.getName());
    	io.setCustCity(selectedCustomer.getCity());
    }
    
    //输入自动完成示例
    public void onAutoSelect(SelectEvent event) {
    	selectedCustomer =  (BmeCustomer)event.getObject();
    	io.setBmeCustomer(selectedCustomer);
    	io.setCustName(selectedCustomer.getName());
    	io.setCustCity(selectedCustomer.getCity());
    }
    
    //处理Transaction is Active
    public void isActiveTransaction() {
		if(db.getEm().getTransaction().isActive())
			db.rollback();
	}

	
	public BmeMaterial getMateriaFromId(String mid) {
		for(BmeMaterial bm : bmeMaterials) {
			if(mid.equals(bm.getId())) {				
				return bm;
			}
		}
		return null;
	}
    
    public BmeContract getIo() {
		return io;
	}

	public void setIo(BmeContract io) {
		this.io = io;
	}

	public List<BmeContProd> getVop() {
		return vop;
	}

	public void setVop(List<BmeContProd> vop) {
		this.vop = vop;
	}

	public List<BmeContPurch> getVoppm() {
		return voppm;
	}

	public void setVoppm(List<BmeContPurch> voppm) {
		this.voppm = voppm;
	}

	public BmeContProd getSelectedp() {
		return selectedp;
	}

	public void setSelectedp(BmeContProd selectedp) {
		this.selectedp = selectedp;
	}

	public BmeContPurch getSelectedpm() {
		return selectedpm;
	}

	public void setSelectedpm(BmeContPurch selectedpm) {
		this.selectedpm = selectedpm;
	}

	public List<SelectItem> getItemsContractStatus() {
		return itemsContractStatus;
	}

	public void setItemsContractStatus(List<SelectItem> itemsContractStatus) {
		this.itemsContractStatus = itemsContractStatus;
	}

	public List<BmeCustomer> getBmeCustomers() {
		return bmeCustomers;
	}

	public void setBmeCustomers(List<BmeCustomer> bmeCustomers) {
		this.bmeCustomers = bmeCustomers;
	}

	public BmeCustomer getSelectedCustomer() {
		return selectedCustomer;
	}

	public void setSelectedCustomer(BmeCustomer selectedCustomer) {
		this.selectedCustomer = selectedCustomer;
	}
	
    public String getContractId() {
		return contractId;
	}

	public void setContractId(String contractId) {
		this.contractId = contractId;
	}

	public String getContractName() {
		return contractName;
	}

	public void setContractName(String contractName) {
		this.contractName = contractName;
	}

	public List<BmeMaterial> getBmeMaterials() {
		return bmeMaterials;
	}

	public void setBmeMaterials(List<BmeMaterial> bmeMaterials) {
		this.bmeMaterials = bmeMaterials;
	}

	public LinkedHashMap<String,String> getItemsSuppliers() {
		return itemsSuppliers;
	}

	public void setItemsSuppliers(LinkedHashMap<String,String> itemsSuppliers) {
		this.itemsSuppliers = itemsSuppliers;
	}

	public String getUploadedFile() {
		return uploadedFile;
	}

	public void setUploadedFile(String uploadedFile) {
		this.uploadedFile = uploadedFile;
	}

	public String getUploadedFileImage() {
		return uploadedFileImage;
	}

	public void setUploadedFileImage(String uploadedFileImage) {
		this.uploadedFileImage = uploadedFileImage;
	}

	public String getUploadForType() {
		return uploadForType;
	}

	public void setUploadForType(String uploadForType) {
		this.uploadForType = uploadForType;
	}

	public String getUploadForId() {
		return uploadForId;
	}

	public void setUploadForId(String uploadForId) {
		this.uploadForId = uploadForId;
	}

	public String getUploadForName() {
		return uploadForName;
	}

	public void setUploadForName(String uploadForName) {
		this.uploadForName = uploadForName;
	}

	public LinkedHashMap<String,String> getItemsSysUsers() {
		return itemsSysUsers;
	}

	public void setItemsSysUsers(LinkedHashMap<String,String> itemsSysUsers) {
		this.itemsSysUsers = itemsSysUsers;
	}

	public String getInitname() {
		return initname;
	}

	public void setInitname(String initname) {
		this.initname = initname;
	}
	public List<BmeMaterial> getSelectedMaterials() {
		return selectedMaterials;
	}
	public void setSelectedMaterials(List<BmeMaterial> selectedMaterials) {
		this.selectedMaterials = selectedMaterials;
	}
}